package com.vision.core.sv.db.mgr;

import java.util.Collection;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.ResultTransformer;

/**
 * Default implementation for {@link ISimpleCriteria}.
 * 
 * @author Mark
 *
 */
public class SimpleCriteria implements ISimpleCriteria {
	
	protected DetachedCriteria impl;
	
	public static SimpleCriteria forClass(Class<?> clazz) {
		return new SimpleCriteria(DetachedCriteria.forClass(clazz));
	}
	
	public SimpleCriteria(DetachedCriteria impl) {
		this.impl = impl;
	}

	@Override
	public DetachedCriteria getDetached() {
		return impl;
	}
	
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	@Override
	public Criterion add(Criterion c) {
		impl.add(c);
		return c;
	}
	
	@Override
	public Criterion notNull(String property) {
		Criterion c = Restrictions.isNotNull(property);
		impl.add( c );
		return c;
	}
	
	@Override
	public Criterion isNull(String property) {
		Criterion c = Restrictions.isNull(property);
		impl.add( c );
		return c;
	}

	@Override
	public Criterion or(Criterion c1, Criterion c2) {
		Criterion c = Restrictions.or(c1, c2);
		impl.add( c );
		return c;
	}

	@Override
	public Criterion eq(String property, Object value) {
		Criterion c = Restrictions.eq(property, value); 
		impl.add( c );
		return c;
	}
	
	@Override
	public Criterion in(String property, Collection<?> values) {
		Criterion c = Restrictions.in(property, values); 
		impl.add( c );
		return c;
	}
	
	@Override
	public Criterion in(String property, Object... values) {
		Criterion c = Restrictions.in(property, values);
		impl.add( c );
		return c;
	}

	@Override
	public Criterion neq(String property, Object value) {
		Criterion c = Restrictions.ne(property, value);
		impl.add( c );
		return c;
	}

	@Override
	public Criterion lt(String property, Object value) {
		Criterion c = Restrictions.lt(property, value);
		impl.add( c );
		return c;
	}

	@Override
	public Criterion leq(String property, Object value) {
		Criterion c = Restrictions.le(property, value);
		impl.add( c );
		return c;
	}

	@Override
	public Criterion gt(String property, Object value) {
		Criterion c = Restrictions.gt(property, value);
		impl.add( c );
		return c;
	}

	@Override
	public Criterion geq(String property, Object value) {
		Criterion c = Restrictions.ge(property, value);
		impl.add( c );
		return c;
	}
	
	@Override
	public Criterion between(String property, Object v1, Object v2) {
		Criterion c = Restrictions.between(property, v1, v2);
		impl.add( c );
		return c;
	}
	
	@Override
	public Criterion inBetween(String property, Object v1, Object v2) {
		Criterion c = Restrictions.ge(property, v1);
		impl.add( c ).add( c = Restrictions.le(property, v2) );
		return c;
	}

	@Override
	public Criterion like(String property, String value) {
		return like(property, value, MatchMode.EXACT);
	}
	
	@Override
	public Criterion like(String property, String value, MatchMode matchMode) {
		Criterion c = Restrictions.like(property, value, matchMode);
		impl.add( c );
		return c;
	}

	@Override
	public Criterion ilike(String property, String value) {
		return ilike(property, value, MatchMode.EXACT);
	}
	
	@Override
	public Criterion ilike(String property, String value, MatchMode matchMode) {
		Criterion c = Restrictions.ilike(property, value, matchMode);
		impl.add( c );
		return c;
	}
	
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	@Override
	public Projection count() {
		Projection p = Projections.rowCount();
		impl.setProjection(p);
		return p;
	}

	@Override
	public void asc(String... properties) {
		for (String property : properties)
			impl.addOrder( Order.asc(property) );
	}

	@Override
	public void desc(String... properties) {
		for (String property : properties)
			impl.addOrder( Order.desc(property) );
	}
	
	@Override
	public ProjectionList group(String... properties) {
		ProjectionList list = Projections.projectionList();
		for (String property : properties)
			list.add( Projections.groupProperty(property) );
		impl.setProjection(list);
		return list;
	}
 
	@Override
	public ProjectionList properties(String... properties) {
		ProjectionList list = Projections.projectionList();
		for (String property : properties)
			list.add( Projections.property(property) );
		impl.setProjection(list);
		return list;
	}
	
	@Override
	public void setResultTransformer(ResultTransformer transformer) {
		impl.setResultTransformer(transformer);
	}
	
}
